package com.demo.personalaccountingbackend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.demo.personalaccountingbackend.dto.LoginRequest;
import com.demo.personalaccountingbackend.dto.LoginResponse;
import com.demo.personalaccountingbackend.entity.User;
import com.demo.personalaccountingbackend.mapper.UserMapper;
import com.demo.personalaccountingbackend.service.UserService;
import com.demo.personalaccountingbackend.utils.JwtUtil;
import com.demo.personalaccountingbackend.utils.SecurityUtils;
import com.demo.personalaccountingbackend.vo.UserVO;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 类描述信息
 *
 * @author zgx
 * @version 1.0
 * @date 2025/10/14$ 10:34$
 */

@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final PasswordEncoder passwordEncoder;

    private final JwtUtil jwtUtil;

    @Override
    public LoginResponse login(LoginRequest loginRequest) {
        // 参数验证
        if (loginRequest == null || !StringUtils.hasText(loginRequest.getUsername())
                || !StringUtils.hasText(loginRequest.getPassword())) {
            return new LoginResponse(false, "用户名和密码不能为空");
        }

        // 使用LambdaQueryWrapper查询用户
        User user = getOne(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, loginRequest.getUsername()));

        if (user == null) {
            return new LoginResponse(false, "用户名不存在");
        }

        // 验证密码
        if (!passwordEncoder.matches(loginRequest.getPassword(), user.getPassword())) {
            return new LoginResponse(false, "密码错误");
        }

        // 生成token
        String token = generateToken(user);

        // 隐藏敏感信息
        user.setPassword(null);

        return new LoginResponse(true, "登录成功", token, user);
    }

    @Override
    public LoginResponse register(User user) {
        // 参数验证
        if (user == null || !StringUtils.hasText(user.getUsername())
                || !StringUtils.hasText(user.getPassword())) {
            return new LoginResponse(false, "用户名和密码不能为空");
        }

        // 检查用户名是否存在
        if (existsByUsername(user.getUsername())) {
            return new LoginResponse(false, "用户名已存在");
        }

        // 加密密码
        user.setPassword(passwordEncoder.encode(user.getPassword()));

        // 使用MyBatis-Plus的save方法，自动处理时间字段（需配置自动填充）
        boolean success = save(user);
        if (!success) {
            return new LoginResponse(false, "注册失败");
        }

        // 生成token
        String token = generateToken(user);
        user.setPassword(null);

        return new LoginResponse(true, "注册成功", token, user);
    }

    @Override
    public User findByUsername(String username) {
        return getOne(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, username));
    }

    @Override
    public boolean existsByUsername(String username) {
        return count(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, username)) > 0;
    }

    @Override
    public boolean checkPassword(String rawPassword, String encodedPassword) {
        return passwordEncoder.matches(rawPassword, encodedPassword);
    }

    /**
     * 生成Token的辅助方法
     */
    private String generateToken(User user) {
        try {
            return jwtUtil.generateToken(user.getId(), user.getUsername());
        } catch (Exception e) {
            System.err.println("生成token失败: " + e.getMessage());
            return "simple-token-" + user.getId() + "-" + System.currentTimeMillis();
        }
    }

    /**
     * 使用MyBatis-Plus的分页查询示例
     */
    public Page<User> getUsersByPage(int pageNum, int pageSize, String username) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.hasText(username)) {
            wrapper.like(User::getUsername, username);
        }
        wrapper.orderByDesc(User::getCreateTime);

        return page(new Page<>(pageNum, pageSize), wrapper);
    }

    /**
     * 批量操作用户状态示例
     */
    @Transactional
    public boolean updateUserStatusBatch(List<Long> userIds, Integer status) {
        return update(new LambdaUpdateWrapper<User>()
                .in(User::getId, userIds)
                .set(User::getStatus, status)
                .set(User::getUpdateTime, LocalDateTime.now()));
    }

    @Override
    public UserVO getUserInfo(Long userId) {
        User user = getById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        return convertToVO(user);
    }

    @Override
    public UserVO getCurrentUserInfo() {
        // 从安全上下文中获取当前用户ID
        Long currentUserId = SecurityUtils.getCurrentUserId();
        return getUserInfo(currentUserId);
    }

    /**
     * 将 User 实体转换为 UserVO（排除敏感信息）
     */
    private UserVO convertToVO(User user) {
        if (user == null) {
            return null;
        }
        UserVO userVO = new UserVO();
        userVO.setId(user.getId());
        userVO.setUsername(user.getUsername());
        userVO.setEmail(user.getEmail());
        userVO.setPhone(user.getPhone());
        userVO.setAvatar(user.getAvatar());
        userVO.setCreateTime(user.getCreateTime());
        userVO.setUpdateTime(user.getUpdateTime());
        userVO.setLastLoginTime(user.getLastLoginTime());
        userVO.setStatus(user.getStatus());

        return userVO;
    }

}